﻿using Ekton_Manage_DomainAbstractions;
using Ekton_Manage_DomainCore;
using Ekton_Manage_Framework.Methods;
using Ekton_Manage_InfrastructureCore.Common;
using Ekton_Manage_InfrastructureCore.SqlSugarHelper;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Claims;
using System.Threading.Tasks;
using static Ekton_Manage_DTO.EnumClass;

namespace Ekton_Manage_InfrastructureCore.Repositories
{
    public class BaseRepository<T, TKey> : IBaseRepository<T, TKey> where T : Entity<TKey>
    {
        private readonly ApplicationDbContent _Mddb;
        private IHttpContextAccessor _accessor;
        public BaseRepository(ApplicationDbContent Mddb, IHttpContextAccessor accessor)
        {
            _Mddb = Mddb;
            _accessor = accessor;
        }

        public List<string> AllowApi = new List<string>() { "/api/Home/GetToken", "/api/ApiLogin/GetToken", "/api/Common/GetCompany", "/api/Common/SendEmail", "/api/ApiLogin/ApiPostUserPass", "/api/Home/PostUserPwd", "/api/ApiLogin/ApiPostUserRegsiter", "/api/Sys/GetCopyRight", "/api/Sys/PutCopyRight", "/api/ApiAgreement/GetAllNewsList", "/api/ApiAgreement/PutAgreementList" };
        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="DataId"></param>
        /// <returns></returns>
        public async Task<bool> DeleteArray(List<TKey> DataId)
        {
            try
            {
                var entity = _Mddb.Set<T>().Where(m => DataId.Contains(m.id)).ToList();
                _Mddb.RemoveRange(entity);
                _Mddb.SaveChanges();
                return entity.Any();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 批量添加
        /// </summary>
        /// <param name="Data"></param>
        /// <returns></returns>
        public async Task<bool> InsertManyData(List<T> Data)
        {
            if (_accessor.HttpContext == null)
            {
                Data.ForEach((m) =>
                {
                    m.create_op_date = DateTime.Now;
                    m.create_op_id = 0;
                    m.create_op_name = "automatic";
                });
                _Mddb.AddRange(Data);
                _Mddb.SaveChanges();
                return Data.Any();
            }
            var claimInfo = (_accessor.HttpContext.AuthenticateAsync().Result.Principal.Claims).FirstOrDefault(t => t.Type.Equals(ClaimTypes.NameIdentifier))?.Value;
            var userInfo = JsonConvert.DeserializeObject<LoginUser>(claimInfo);
            Data.ForEach((m) =>
            {
                m.create_op_date = DateTime.Now;
                m.create_op_id = userInfo.id;
                m.create_op_name = userInfo.name;
            });
            _Mddb.AddRange(Data);
            _Mddb.SaveChanges();
            return Data.Any();
        }

        /// <summary>
        /// 根据id查询单条数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<T> QuerySingleData(TKey id)
        {
            return _Mddb.Set<T>().Find(id);
        }
        /// <summary>
        /// 根据id查询单条数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<T> QuerySingleData(string id)
        {
            return _Mddb.Set<T>().Find(Convert.ToInt32(id));
        }
        /// <summary>
        /// 查询单条数据
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public async Task<T> QuerySingleData(Expression<Func<T, bool>> expression)
        {
            return _Mddb.Set<T>().AsNoTracking().Where(expression).FirstOrDefault();
        }

        /// <summary>
        /// 查询单条数据
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public async Task<T> QuerySingleData(Expression<Func<T, bool>> expression, IEnumerable<Func<T, dynamic>> sorts, sortType sortType)
        {
            var query = _Mddb.Set<T>().AsNoTracking().Where(expression);
            var sortQuery = GetSortQueryBySorts(query, sorts, sortType);
            return sortQuery.FirstOrDefault();
        }


        /// <summary>
        /// 删除单条数据[伪删除]
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DeleteSingleData(TKey id)
        {
            var entity = _Mddb.Set<T>().Find(id);
            if (entity == null)
                return false;
            _Mddb.Remove<T>(entity);
            _Mddb.SaveChanges();
            return true;
        }

        /// <summary>
        /// 修改单条数据
        /// </summary>
        /// <param name="Object"></param>
        /// <returns></returns>
        public async Task<Tuple<bool, int>> UpdateSingleData(T Object)
        {
            if (_accessor.HttpContext == null)
            {
                Object.edit_op_id = 0;
                Object.edit_op_name = "";
                Object.edit_op_date = DateTime.Now;

                _Mddb.Set<T>().Update(Object);
                _Mddb.SaveChanges();
                return Tuple.Create<bool, int>(true, 0);
            }
            var Identity = _accessor.HttpContext.AuthenticateAsync().Result.Principal;
            string claimInfo = string.Empty;
            if (Identity != null) claimInfo = (_accessor.HttpContext.AuthenticateAsync().Result.Principal.Claims).FirstOrDefault(t => t.Type.Equals(ClaimTypes.NameIdentifier))?.Value;
            var userInfo = JsonConvert.DeserializeObject<LoginUser>(claimInfo);
            //if (entity != null)
            //{
            //Object.create_op_id = entity.create_op_id;
            //Object.create_op_name = entity.create_op_name;
            //Object.create_op_date = entity.create_op_date;
            Object.edit_op_id = userInfo == null ? 0 : userInfo.id;
            Object.edit_op_name = userInfo == null ? "" : userInfo.name;
            Object.edit_op_date = DateTime.Now;
            //}
            _Mddb.Set<T>().Update(Object);
            _Mddb.SaveChanges();
            return Tuple.Create<bool, int>(true, 0);
        }

        /// <summary>
        /// 修改多条数据
        /// </summary>
        /// <param name="Object"></param>
        /// <returns></returns>
        public async Task<Tuple<bool, int>> UpdateManyData(List<T> Data)
        {
            //var headerData = _accessor.HttpContext.Request.Headers["userInfo"].ToString();
            //var userInfo = JsonConvert.DeserializeObject<LoginUser>(headerData);
            Data.ForEach((m) =>
            {
                m.edit_op_date = DateTime.Now;
                m.edit_op_id = 1;
                m.edit_op_name = "admin";
            });
            _Mddb.UpdateRange(Data);
            _Mddb.SaveChanges();
            return Tuple.Create<bool, int>(true, 0);
        }

        /// <summary>
        /// 添加单条数据
        /// </summary>
        /// <param name="Object"></param>
        /// <returns></returns>
        public async Task<Tuple<bool, int>> InsertSingleData(T Object)
        {

            string claimInfo = "";
            if (!AllowApi.Contains(_accessor.HttpContext.Request.Path))
                claimInfo = (_accessor.HttpContext.AuthenticateAsync().Result.Principal.Claims).FirstOrDefault(t => t.Type.Equals(ClaimTypes.NameIdentifier))?.Value;
            var userInfo = JsonConvert.DeserializeObject<LoginUser>(claimInfo);
            //Object.id = Object.id != null ? Object.id : (TKey)Convert.ChangeType(Guid.NewGuid().ToString().Replace("-", string.Empty), typeof(TKey));
            Object.create_op_date = DateTime.Now;
            Object.create_op_name = userInfo == null ? "" : userInfo.name;
            Object.create_op_id = userInfo == null ? 0 : userInfo.id;

            _Mddb.Set<T>().Add(Object);
            _Mddb.SaveChanges();
            return Tuple.Create<bool, int>(true, Convert.ToInt32(Object.id));
        }

        /// <summary>
        /// 添加/修改单条数据
        /// </summary>
        /// <param name="Object"></param>
        /// <returns></returns>
        public async Task<Tuple<bool, int>> InsertOrUpdateSingleData(T Object)
        {
            var entity = _Mddb.Set<T>().AsNoTracking().Where(m => Convert.ToString(m.id) == Convert.ToString(Object.id)).FirstOrDefault();
            var headerData = _accessor.HttpContext.Request.Headers["userInfo"].ToString();
            var userInfo = JsonConvert.DeserializeObject<LoginUser>(headerData);
            if (entity == null)
            {
                Object.create_op_date = DateTime.Now;
                Object.create_op_name = userInfo == null ? "" : userInfo.name;
                Object.create_op_id = userInfo == null ? 0 : userInfo.id;
                _Mddb.Set<T>().Add(Object);
                _Mddb.SaveChanges();
            }
            else if (entity != null)
            {
                Object.edit_op_id = userInfo == null ? 0 : userInfo.id;
                Object.edit_op_name = userInfo == null ? "" : userInfo.name;
                Object.edit_op_date = DateTime.Now;
                _Mddb.Set<T>().Update(Object);
                _Mddb.SaveChanges();
            }
            return Tuple.Create<bool, int>(true, 1);
        }


        /// <summary>
        /// 单表/视图分页查询
        /// </summary>
        /// <param name="queryDataParame"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        public async Task<Tuple<List<T>, int>> QueryPageData(QueryDataParame queryDataParame, Expression<Func<T, bool>> expression)
        {
            var List = _Mddb.Set<T>().Where(expression)
                                     .OrderByDescending(m => m.create_op_date)
                                     .Skip((queryDataParame.pageIndex - 1) * queryDataParame.pageSize)
                                     .Take(queryDataParame.pageSize)
                                     .ToList();
            int total = _Mddb.Set<T>().Where(expression).Count();
            return Tuple.Create<List<T>, int>(List, total);
        }

        public async Task<Tuple<List<T>, int>> QueryPageData(QueryDataParame queryDataParame, Expression<Func<T, bool>> expression, Func<T, dynamic> sort)
        {
            var List = _Mddb.Set<T>().Where(expression)
                                     .OrderBy(sort)
                                     .Skip((queryDataParame.pageIndex - 1) * queryDataParame.pageSize)
                                     .Take(queryDataParame.pageSize)
                                     .ToList();
            int total = _Mddb.Set<T>().Where(expression).Count();
            return Tuple.Create<List<T>, int>(List, total);
        }

        /// <summary>
        /// 单表/视图分页查询
        /// </summary>
        /// <param name="queryDataParame">查询的参数</param>
        /// <param name="expression">参数的拼接</param>
        /// <param name="sort">排序的字段</param>
        /// <param name="sortType">排序的类型,升序或降序</param>
        /// <returns></returns>
        public async Task<Tuple<List<T>, int>> QueryPageData(QueryDataParame queryDataParame, Expression<Func<T, bool>> expression, Func<T, dynamic> sort, sortType sortType)
        {
            var list = new List<T>();
            if (sortType == sortType.desc)
                list = _Mddb.Set<T>().Where(expression)
                                     .OrderByDescending(sort)
                                     .Skip((queryDataParame.pageIndex - 1) * queryDataParame.pageSize)
                                     .Take(queryDataParame.pageSize)
                                     .ToList();
            else
                list = _Mddb.Set<T>().Where(expression)
                                    .OrderBy(sort)
                                    .Skip((queryDataParame.pageIndex - 1) * queryDataParame.pageSize)
                                    .Take(queryDataParame.pageSize)
                                    .ToList();
            int total = _Mddb.Set<T>().Where(expression).Count();
            return Tuple.Create<List<T>, int>(list, total);
        }

        /// <summary>
        /// 单表/视图分页查询
        /// </summary>
        /// <param name="queryDataParame">查询的参数</param>
        /// <param name="expression">参数的拼接</param>
        /// <param name="sort">排序的字段</param>
        /// <param name="sortType">排序的类型,升序或降序</param>
        /// <returns></returns>
        public async Task<Tuple<List<T>, int>> QueryPageData(QueryDataParame queryDataParame, Expression<Func<T, bool>> expression, IEnumerable<Func<T, dynamic>> sorts, sortType sortType)
        {
            var list = new List<T>();
            IQueryable<T> query = _Mddb.Set<T>().Where(expression);
            IOrderedEnumerable<T> sortQuery = GetSortQueryBySorts(query, sorts, sortType);
            list = sortQuery.Skip((queryDataParame.pageIndex - 1) * queryDataParame.pageSize)
                                     .Take(queryDataParame.pageSize)
                                     .ToList();
            int total = _Mddb.Set<T>().Where(expression).Count();
            return Tuple.Create<List<T>, int>(list, total);
        }

        /// <summary>
        /// 单表查询
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public async Task<List<T>> QueryTableList(Expression<Func<T, bool>> expression)
        {
            return _Mddb.Set<T>().Where(expression).ToList();
        }

        /// <summary>
        /// 查询数量
        /// </summary>
        /// <returns></returns>
        public async Task<int> QueryCount(Expression<Func<T, bool>> expression)
        {
            return _Mddb.Set<T>().Where(expression).Count();
        }

        IOrderedEnumerable<T> GetSortQueryBySorts(IQueryable<T> query, IEnumerable<Func<T, dynamic>> sorts, sortType sortType)
        {
            IOrderedEnumerable<T> sortQuery = null;
            for (int i = 0, l = sorts.Count(); i < l; i++)
            {
                if (i == 0)
                {
                    if (sortType == sortType.desc)
                        sortQuery = query.OrderByDescending(sorts.ElementAt(i));
                    else
                        sortQuery = query.OrderBy(sorts.ElementAt(i));
                }
                else
                {
                    if (sortType == sortType.desc)
                        sortQuery = sortQuery.ThenByDescending(sorts.ElementAt(i));
                    else
                        sortQuery = sortQuery.ThenBy(sorts.ElementAt(i));
                }
            }
            return sortQuery;
        }


        public virtual void Dispose()
        {
            if (_Mddb != null)
            {
                _Mddb.Dispose();
            }
        }

    }
}
